package com.dev.bbs.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Service;

import com.dev.bbs.bean.RankCommentArt;
import com.dev.bbs.bean.RankCommentUser;
import com.dev.bbs.domain.BbsArticle;
import com.dev.bbs.domain.BbsComment;
import com.dev.bbs.domain.BbsMentLike;
import com.dev.bbs.domain.BbsUser;
import com.dev.bbs.mapper.BbsCommentMapper;
import com.dev.bbs.service.IBbsArticleService;
import com.dev.bbs.service.IBbsCommentService;
import com.dev.bbs.service.IBbsMentLikeService;
import com.dev.bbs.service.IBbsUserService;
import com.dev.common.exception.BusinessException;
import com.dev.common.utils.DateUtils;

/**
 * 帖子评论Service业务层处理
 * 
 * @author dev
 * @date 2019-09-23
 */
@Service
public class BbsCommentServiceImpl implements IBbsCommentService
{
    private final static String          RANK_WEEK_COMMENT_USER = "rank_week_comment_user:";

    private final static String          RANK_WEEK_COMMENT_ART  = "rank_week_comment_art:";

    @Autowired
    private BbsCommentMapper             bbsCommentMapper;

    @Autowired
    private IBbsMentLikeService          mentLikeService;

    @Autowired
    private IBbsArticleService           bbsArticleService;

    @Autowired
    private IBbsUserService              bbsUserService;

    @Resource(name = "redisTemplate")
    private ZSetOperations<String, Long> zSops;

    /**
     * 查询帖子评论
     * 
     * @param mentId 帖子评论ID
     * @return 帖子评论
     */
    @Override
    public BbsComment selectBbsCommentById(Long mentId)
    {
        return bbsCommentMapper.selectByPrimaryKey(mentId);
    }

    /**
     * 查询帖子评论列表
     * 
     * @param bbsComment 帖子评论
     * @return 帖子评论
     */
    @Override
    public List<BbsComment> selectBbsCommentList(BbsComment bbsComment)
    {
        return bbsCommentMapper.selectBbsCommentList(bbsComment);
    }

    /**
     * 新增帖子评论
     * 
     * @param bbsComment 帖子评论
     * @return 结果
     */
    @Override
    public int insertBbsComment(BbsComment bbsComment)
    {
        bbsComment.setCreateTime(DateUtils.getNowDate());
        int index = bbsCommentMapper.insertSelective(bbsComment);
        if (index == 1)
        {
            addWeekUserScore(bbsComment.getAuthor());
            addWeekArtScore(bbsComment.getArtId());
            bbsArticleService.addComment(bbsComment.getArtId(), index);
            return index;
        }
        return 0;
    }

    /**
     * 修改帖子评论
     * 
     * @param bbsComment 帖子评论
     * @return 结果
     */
    @Override
    public int updateBbsComment(BbsComment bbsComment)
    {
        return bbsCommentMapper.updateByPrimaryKeySelective(bbsComment);
    }

    /**
     * 删除帖子评论对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteBbsCommentByIds(String ids)
    {
        return bbsCommentMapper.deleteByIds(ids);
    }

    /**
     * 删除帖子评论信息
     * 
     * @param mentId 帖子评论ID
     * @return 结果
     */
    public int deleteBbsCommentById(Long mentId, long userId)
    {
        return bbsCommentMapper.delete(new BbsComment().setMentId(mentId).setAccept(false).setAuthor(userId));
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.dev.bbs.service.IBbsCommentService#like(java.lang.Long, long)
     */
    @Override
    public int like(Long mentId, long userId)
    {
        BbsMentLike bbsMentLike = new BbsMentLike().setMentId(mentId).setUserId(userId);
        if (mentLikeService.insertBbsMentLike(bbsMentLike) > 0)
        {
            return bbsCommentMapper.addLike(mentId);
        }
        return 0;
    }

    @Override
    public int unlike(Long mentId, long userId)
    {
        BbsMentLike bbsMentLike = new BbsMentLike().setMentId(mentId).setUserId(userId);
        if (mentLikeService.deleteLike(bbsMentLike) > 0)
        {
            return bbsCommentMapper.subLike(mentId);
        }
        return 0;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.dev.bbs.service.IBbsCommentService#getRankComment()
     */
    @Override
    public List<RankCommentUser> getRankCommentUser()
    {
        String key = RANK_WEEK_COMMENT_USER + DateUtils.getWeekOfYear(new Date());
        Set<TypedTuple<Long>> tuples = zSops.reverseRangeWithScores(key, 0, 19);
        List<RankCommentUser> ranks = new ArrayList<RankCommentUser>();
        for (TypedTuple<Long> tuple : tuples)
        {
            Number uid = tuple.getValue();
            RankCommentUser rank = new RankCommentUser().setUid(uid.longValue())
                    .setComment(tuple.getScore().longValue());
            ranks.add(rank);
        }
        if (ranks.size() > 0)
        {
            List<RankCommentUser> users = bbsCommentMapper.getRankCommentUser(ranks);
            List<RankCommentUser> result = ranks.stream()
                    .flatMap(x -> users.stream().filter(y -> x.getUid().equals(y.getUid()))
                            .map(y -> new RankCommentUser(y.getUid(), y.getNickname(), y.getAvatar(), x.getComment())))
                    .collect(Collectors.toList());
            return result;
        }
        return null;
    }

    @Override
    public List<RankCommentArt> getRankCommentArt()
    {
        String key = RANK_WEEK_COMMENT_ART + DateUtils.getWeekOfYear(new Date());
        Set<TypedTuple<Long>> tuples = zSops.reverseRangeWithScores(key, 0, 19);
        List<RankCommentArt> ranks = new ArrayList<RankCommentArt>();
        for (TypedTuple<Long> tuple : tuples)
        {
            Number aid = tuple.getValue();
            RankCommentArt rank = new RankCommentArt().setAid(aid.longValue()).setComment(tuple.getScore().longValue());
            ranks.add(rank);
        }
        if (ranks.size() > 0)
        {
            List<RankCommentArt> arts = bbsCommentMapper.getRankCommentArt(ranks);
            List<RankCommentArt> result = ranks.stream()
                    .flatMap(x -> arts.stream().filter(y -> x.getAid().equals(y.getAid()))
                            .map(y -> new RankCommentArt(x.getComment(), y.getTitle(), x.getAid())))
                    .collect(Collectors.toList());
            return result;
        }
        return null;
    }

    /**
     * 回帖榜积分+1 用户为排序对象
     * @param userId 用户编号
     * @return
     * @author zmr
     */
    private boolean addWeekUserScore(long userId)
    {
        String key = RANK_WEEK_COMMENT_USER + DateUtils.getWeekOfYear(new Date());
        double r = zSops.incrementScore(key, userId, 1l);
        return r > 0;
    }

    /**
     * 热议榜积分+1 帖子为排序对象
     * @param artId 帖子编号
     * @return
     * @author zmr
     */
    private boolean addWeekArtScore(long artId)
    {
        String key = RANK_WEEK_COMMENT_ART + DateUtils.getWeekOfYear(new Date());
        double r = zSops.incrementScore(key, artId, 1l);
        return r > 0;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.dev.bbs.service.IBbsArticleService#accept(long, long, long)
     */
    @Override
    public int accept(long artId, long userId, long mentId)
    {
        BbsArticle article = bbsArticleService.selectBbsArticleById(artId);
        if (null != article && article.getAuthor().equals(userId))
        {
            BbsComment comment = selectBbsCommentById(mentId);
            if (null != comment)
            {
                BbsUser acceptUser = bbsUserService.selectBbsUserById(comment.getAuthor());
                if (acceptUser.getUserId().equals(userId))
                {
                    throw new BusinessException("不能采纳自己的答案");
                }
                if (bbsArticleService.updateBbsArticle(new BbsArticle().setId(artId).setStatus(9)) > 0)
                {
                    return updateBbsComment(new BbsComment().setMentId(mentId).setAccept(true));
                }
            }
        }
        return 0;
    }
}
